﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Web.UI;
using System.Web.UI.WebControls;
using TPG.SharePoint.Workflow.Controls.Design;

namespace TPG.SharePoint.Workflow.Controls
{   
    [ToolboxData("<{0}:InputFormControl runat=\"server\"></{0}:InputFormControl>"),
    Designer(typeof(InputFormControlDesigner))]
    public class InputFormControl
        : CompositeControl
    {
        ITemplate _controlTemplate;
        ITemplate _labelTemplate;
        ITemplate _exampleTemplate;

        TableCell _controlTemplateContainer;
        TableCell _exampleTemplateContainer;
        TableCell _labelTemplateContainer;
        PlaceHolder _exampleRowContainer;
        
        TableCell _controlRowFirstCell;
        Spacer _controlRowFirstCellSpacer;

        [DefaultValue(""),
        Category("Appearance"),
        Description("The label for the input control.")]
        public string LabelText
        {
            get { return (string)ViewState["LabelText"] ?? String.Empty; }
            set
            {
                if (value != LabelText)
                {
                    ViewState["LabelText"] = value;
                }
            }
        }

        [DefaultValue(""),
        Category("Appearance"),
        Description("A text showing a correct input value.")]
        public string ExampleText
        {
            get { return (string)ViewState["ExampleText"] ?? String.Empty; }
            set
            {
                if (value != ExampleText)
                {
                    ViewState["ExampleText"] = value;
                }
            }
        }

        [PersistenceMode(PersistenceMode.InnerProperty),
        TemplateContainer(typeof(InputFormControl)),
        TemplateInstance(TemplateInstance.Single),
        DefaultValue(null),
        Browsable(false)]
        public ITemplate LabelTemplate
        {
            get { return _labelTemplate; }
            set
            {
                _labelTemplate = value;
                _labelTemplateContainer = null;
                ChildControlsCreated = false;
            }
        }

        [PersistenceMode(PersistenceMode.InnerProperty),
        TemplateContainer(typeof(InputFormControl)),
        TemplateInstance(TemplateInstance.Single),
        DefaultValue(null),
        Browsable(false)]
        public ITemplate ExampleTemplate
        {
            get { return _exampleTemplate; }
            set
            {
                _exampleTemplate = value;
                _exampleTemplateContainer = null;
                ChildControlsCreated = false;
            }
        }

        [PersistenceMode(PersistenceMode.InnerProperty),
        TemplateContainer(typeof(InputFormControl)),
        TemplateInstance(TemplateInstance.Single),
        DefaultValue(null),
        Browsable(false)]
        public ITemplate ControlTemplate
        {
            get { return _controlTemplate; }
            set
            {
                _controlTemplate = value;
                _controlTemplateContainer = null;
                ChildControlsCreated = false;
            }
        }

        [Description("Indicates how much to indent the control compared to the label."),
        Category("Appearance"),
        DefaultValue(false)]
        public bool SmallIndent
        {
            get { return (bool?)ViewState["SmallIndent"] ?? false; }
            set 
            { 
                ViewState["SmallIndent"] = value;
                if (ChildControlsCreated)
                {
                    ApplyControlRowProperties();
                }
            }
        }

        protected int IndentSize
        {
            get
            {
                return SmallIndent ? 3 : 11;
            }
        }

        protected override void OnInit(EventArgs e)
        {
            EnsureChildControls();
            base.OnInit(e);
        }

        protected override void CreateChildControls()
        {
            Controls.Clear();
            Controls.Add(CreateLabelRow());
            Controls.Add(CreateSpacerRow(3));
            Controls.Add(CreateControlRow());
            Controls.Add(CreateExampleRow());
            Controls.Add(CreateSpacerRow(6));
            ChildControlsCreated = true;
            ClearChildViewState();
        }

        protected override void OnPreRender(EventArgs e)
        {
            EnsureChildControls();
            _exampleRowContainer.Visible =
                _exampleTemplate != null ||
                String.IsNullOrEmpty(ExampleText) == false;
            base.OnPreRender(e);
        }

        protected override void Render(HtmlTextWriter writer)
        {
            RenderChildren(writer);
        }

        protected override IDictionary GetDesignModeState()
        {
            IDictionary state = base.GetDesignModeState();
            state["LabelTemplateContainer"] = _labelTemplateContainer;
            state["ExampleTemplateContainer"] = _exampleTemplateContainer;
            state["ControlTemplateContainer"] = _controlTemplateContainer;
            return state;
        }

        TableRow CreateLabelRow()
        {
            TableRow firstRow = new TableRow();
            if (_labelTemplateContainer == null)
            {
                _labelTemplateContainer = new TableCell();
                _labelTemplateContainer.ColumnSpan = 2;
                _labelTemplateContainer.CssClass = "ms-authoringcontrols";
                _labelTemplateContainer.Wrap = false;
                ITemplate labelTemplate = _labelTemplate ?? new DefaultLabelTemplate(this);
                labelTemplate.InstantiateIn(_labelTemplateContainer);
            }
            firstRow.Cells.Add(_labelTemplateContainer);
            return firstRow;
        }

        TableRow CreateSpacerRow(int height)
        {
            TableRow row = new TableRow();
            TableCell cell = new TableCell();
            Spacer spacer = new Spacer(1, height);
            cell.Controls.Add(spacer);
            row.Cells.Add(cell);
            return row;
        }

        TableRow CreateControlRow()
        {
            TableRow row = new TableRow();
            _controlRowFirstCell = new TableCell();
            _controlRowFirstCellSpacer = new Spacer();

            if (_controlTemplateContainer == null)
            {
                _controlTemplateContainer = new TableCell();
                _controlTemplateContainer.CssClass = "ms-authoringcontrols";
                _controlTemplateContainer.Width = Unit.Percentage(99);
                if (_controlTemplate != null)
                {
                    _controlTemplate.InstantiateIn(_controlTemplateContainer);
                }
            }
            _controlRowFirstCell.Controls.Add(_controlRowFirstCellSpacer);
            row.Cells.AddRange(new TableCell[] { 
                _controlRowFirstCell, _controlTemplateContainer });
            ApplyControlRowProperties();
            return row;
        }

        PlaceHolder CreateExampleRow()
        {
            _exampleRowContainer = new PlaceHolder();
            TableRow row = new TableRow();
            TableCell firstcell = new TableCell();
            Spacer spacer = new Spacer(1, 1);
            if (_exampleTemplateContainer == null)
            {
                _exampleTemplateContainer = new TableCell();
                _exampleTemplateContainer.CssClass = "ms-authoringcontrols";
                ITemplate template = _exampleTemplate ?? new DefaultExampleTemplate(this);
                template.InstantiateIn(_exampleTemplateContainer);
            }
            firstcell.Controls.Add(spacer);
            row.Cells.AddRange(new TableCell[] { firstcell, _exampleTemplateContainer });
            _exampleRowContainer.Controls.Add(row);
            return _exampleRowContainer;
        }


        void ApplyControlRowProperties()
        {
            _controlRowFirstCellSpacer.Width = new Unit(IndentSize);
            _controlRowFirstCellSpacer.Height = new Unit(1);
            _controlRowFirstCell.Width = new Unit(IndentSize);
        }

        class DefaultLabelTemplate
            : ITemplate
        {
            InputFormControl _owner;
            LiteralControl _literal;

            public DefaultLabelTemplate(InputFormControl owner)
            {
                _owner = owner;
                _owner.PreRender += new EventHandler(Owner_PreRender);
            }

            public void InstantiateIn(Control container)
            {
                string label = _owner.LabelText;
                if (String.IsNullOrEmpty(label) && _owner.DesignMode)
                {
                    label = "[LabelText]";
                }
                _literal = new LiteralControl(label);
                container.Controls.Add(_literal);
            }

            void Owner_PreRender(object sender, EventArgs e)
            {
                _literal.Text = _owner.LabelText;
            }
        }

        class DefaultExampleTemplate
            : ITemplate
        {
            InputFormControl _owner;
            LiteralControl _literal;

            public DefaultExampleTemplate(InputFormControl owner)
            {
                _owner = owner;
                _owner.PreRender += new EventHandler(Owner_PreRender);
            }

            public void InstantiateIn(Control container)
            {
                string example = _owner.ExampleText;
                if (String.IsNullOrEmpty(example) && _owner.DesignMode)
                {
                    example = "[ExampleText]";
                }
                _literal = new LiteralControl(example);
                container.Controls.Add(_literal);
            }

            void Owner_PreRender(object sender, EventArgs e)
            {
                _literal.Text = _owner.ExampleText;
            }
        }

    }
}
